home *** CD-ROM | disk | FTP | other *** search
- /*
-
- File: readpart.c
-
- Copyright (C) 1998-2004 Christophe GRENIER <grenier@cgsecurity.org>
-
- This software is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- */
-
-
- #include <stdio.h>
- #include <stdlib.h> /* qsort */
- #include <ctype.h> /* toupper, tolower */
- #include "types.h"
- #include "common.h"
- #include "readpart.h"
- #include "testdisk.h"
- #include "fnctdsk.h"
- #include "analyse.h"
- #include "lang.h"
- #include "intrface.h"
-
- static t_list_part *get_ext_data(t_param_disk *disk_car, t_list_part *list_part, const int debug);
- static void test_MBR_data(t_list_part *list_part);
- static int test_MBR_over(t_param_disk *disk_car,t_list_part *list_part);
-
- int get_geometry_from_mbr(const unsigned char *buffer, const int debug, t_CHS *geometry)
- {
- unsigned int i;
- geometry->cylinder=0;
- geometry->head=0;
- geometry->sector=0;
- if((buffer[0x1FE]!=(unsigned char)0x55)||(buffer[0x1FF]!=(unsigned char)0xAA))
- {
- return 1;
- }
- for(i=0;i<4;i++)
- {
- const struct partition_dos *p=pt_offset_const(buffer,i);
- if(p->sys_ind!=0)
- {
- if(geometry->cylinder<e_cyl(p))
- geometry->cylinder=e_cyl(p);
- if(geometry->head<e_head(p))
- geometry->head=e_head(p);
- if(geometry->sector<e_sect(p))
- geometry->sector=e_sect(p);
- }
- }
- if(geometry->sector>0)
- {
- ecrit_rapport("Geometry from MBR: head=%u sector=%u\n",geometry->head+1,geometry->sector);
- }
- return 0;
- }
-
- t_list_part *read_part(t_param_disk *disk_car, const int debug)
- {
- unsigned char buffer[SECTOR_SIZE];
- t_list_part *new_list_part=NULL;
- unsigned int i;
- int res=0;
- t_CHS geometry;
- aff_buffer(BUFFER_RESET,"Q");
- if(read_MBR(disk_car,&buffer)!=0)
- return NULL;
- if(get_geometry_from_mbr(buffer,debug,&geometry)!=0)
- {
- aff_buffer(BUFFER_ADD,msg_TBL_NMARK);
- return NULL;
- }
- for(i=0;i<4;i++)
- {
- const struct partition_dos *p=pt_offset(buffer,i);
- status_type_t status=STATUS_PRIM;
- switch(p->sys_ind)
- {
- case P_NO_OS:
- break;
- case P_EXTENDX:
- case P_EXTENDED:
- case P_LINUXEXTENDX:
- status=STATUS_EXT;
- /* don't put a break */
- default:
- {
- t_diskext *new_partition=partition_new();
- entry2partition(disk_car, 0, new_partition, p, status,i+1,debug);
- if(debug>1)
- aff_entry_rapport(p);
- aff_part_buffer(AFF_PART_ORDER,disk_car,new_partition);
- if(new_partition->errcode!=BAD_NOERR)
- {
- aff_buffer(BUFFER_ADD,"%s\n",errmsg_entry2partition(new_partition->errcode));
- res|=1;
- FREE(new_partition);
- }
- else
- {
- new_list_part=insert_new_partition(new_list_part,new_partition);
- }
- }
- break;
- }
- }
- if(res==0)
- {
- test_MBR_data(new_list_part);
- if(test_MBR_over(disk_car,new_list_part)==0)
- new_list_part=get_ext_data(disk_car,new_list_part,debug);
- }
- return new_list_part;
- }
-
- static void test_MBR_data(t_list_part *list_part)
- {
- t_list_part *element;
- unsigned int nb_dos=0, nb_hidden=0, nb_mb=0, nb_ext=0, nb_boot=0;
- wdoprintf(stdscr,msg_PART_HEADER);
- for(element=list_part;element!=NULL;element=element->next)
- {
- const t_diskext *partition=element->part;
- switch(partition->status)
- {
- case STATUS_PRIM_BOOT:
- nb_boot++;
- case STATUS_PRIM:
- switch(partition->part_type)
- {
- case P_12FAT:
- case P_16FAT:
- case P_16FATBD:
- nb_dos++;
- break;
- case P_16FATBDH:
- case P_16FATH:
- case P_NTFSH:
- nb_hidden++;
- break;
- case P_OS2MB:
- nb_mb++;
- break;
- }
- break;
- case STATUS_EXT:
- nb_ext++;
- break;
- default:
- ecrit_rapport("test_MBR_data: severe error\n");
- break;
- }
- }
- if(nb_dos>1)
- aff_buffer(BUFFER_ADD,msg_ONLY_ONE_DOS);
- if(nb_ext>1)
- aff_buffer(BUFFER_ADD,msg_ONLY_ONE_EXT);
- /* S'il y a des partitions caches, il faut un MB */
- /* Obsolete
- if(nb_hidden>0 && nb_mb==0)
- aff_buffer(BUFFER_ADD,msg_NO_OS2MB);
- */
- /* Nombre de partition bootable */
- if(nb_boot==0)
- aff_buffer(BUFFER_ADD,msg_NO_BOOTABLE);
- else
- if(nb_boot>1)
- aff_buffer(BUFFER_ADD,msg_ONLY1MUSTBOOT);
- }
-
- static t_list_part *get_ext_data(t_param_disk *disk_car, t_list_part *list_part, const int debug)
- {
- t_list_part *element;
- int res=0;
- t_diskext *partition_main_ext=NULL;
- for(element=list_part;element!=NULL;element=element->next)
- {
- if(element->part->status==STATUS_EXT)
- partition_main_ext=element->part;
- }
- if(partition_main_ext!=NULL)
- {
- t_diskext *partition_ext=partition_main_ext;
- t_diskext *partition_next_ext=NULL;
- unsigned int i;
- unsigned int order=5;
- do
- {
- unsigned char buffer[SECTOR_SIZE];
- int nb_hidden=0, nb_mb=0, nb_part=0, nb_ext=0, nb_boot=0;
- if(disk_car->read(disk_car,1, &buffer, partition_ext->lba)!=0)
- return list_part;
- if((buffer[0x1FE]!=(unsigned char)0x55)||(buffer[0x1FF]!=(unsigned char)0xAA))
- {
- aff_buffer(BUFFER_ADD,"\ntest_logical: " msg_TBL2_NMARK);
- return list_part;
- }
- for(i=0;i<4;i++)
- {
- const struct partition_dos *p=pt_offset(buffer,i);
- if(p->boot_ind==(unsigned char)0x80)
- nb_boot++;
- switch(p->sys_ind)
- {
- case P_16FATBDH:
- case P_16FATH:
- case P_NTFSH:
- nb_hidden++;
- break;
- case P_OS2MB:
- nb_mb++;
- break;
- case P_EXTENDX:
- case P_EXTENDED:
- case P_LINUXEXTENDX:
- nb_ext++;
- break;
- case P_NO_OS:
- break;
- default:
- nb_part++;
- }
- }
- if(nb_hidden>0)
- aff_buffer(BUFFER_ADD,"Partition musn't be hidden\n");
- if(nb_mb>0)
- aff_buffer(BUFFER_ADD,"Multiboot must be a primary partition, not a logical\n");
- if(nb_ext>1)
- aff_buffer(BUFFER_ADD,"A logical partition musn't have more than one link to another logical partition\n");
- if(nb_part>1)
- aff_buffer(BUFFER_ADD,"A logical partition must contain only one partition\n");
- if(nb_boot>0)
- aff_buffer(BUFFER_ADD,"Logical partition musn't be bootable\n");
- partition_next_ext=NULL;
- for(i=0;i<4;i++)
- {
- const struct partition_dos *p=pt_offset(buffer,i);
- if(p->sys_ind!=0)
- {
- t_diskext *new_partition=partition_new();
- new_partition->order=order;
- if(debug>1)
- aff_entry_rapport(p);
- if(is_extended(p->sys_ind))
- {
- partition_next_ext=new_partition;
- entry2partition(disk_car, partition_main_ext->lba, new_partition, p, STATUS_EXT_IN_EXT,order,debug);
- aff_part_buffer(AFF_PART_ORDER,disk_car,new_partition);
- if(new_partition->errcode!=BAD_NOERR)
- {
- aff_buffer(BUFFER_ADD,"(p): %s\n",errmsg_entry2partition(new_partition->errcode));
- res=1;
- }
- else
- {
- if((new_partition->lba<=partition_main_ext->lba) ||
- (new_partition->lba+new_partition->part_size-1 > partition_main_ext->lba+partition_main_ext->part_size-1))
- { /* Must be IN partition_main_ext */
- res=1;
- aff_buffer(BUFFER_ADD,"Must be in extended partition\n");
- aff_part_buffer(AFF_PART_ORDER,disk_car,partition_main_ext);
- aff_part_buffer(AFF_PART_ORDER,disk_car,new_partition);
- }
- else
- {
- for(element=list_part;element!=NULL;element=element->next)
- {
- t_diskext *partition=element->part;
- if(partition->status==STATUS_EXT_IN_EXT)
- {
- if(((partition->lba>=new_partition->lba) && (partition->lba<=new_partition->lba+new_partition->part_size-1)) ||
- ((partition->lba+partition->part_size-1>=new_partition->lba) && (partition->lba+partition->part_size-1<=new_partition->lba+partition->part_size-1)))
- { /* New Partition start or end musn't been in partition */
- res=1;
- aff_buffer(BUFFER_ADD, "Logical partition must be in its own extended partition\n");
- aff_part_buffer(AFF_PART_ORDER,disk_car,partition);
- aff_part_buffer(AFF_PART_ORDER,disk_car,new_partition);
- }
- }
- }
- }
- }
- }
- else
- {
- entry2partition(disk_car,partition_ext->lba, new_partition, p, STATUS_LOG,order,debug);
- order++;
- if(debug>1)
- aff_entry_rapport(p);
- aff_part_buffer(AFF_PART_ORDER,disk_car,new_partition);
- if(new_partition->errcode!=BAD_NOERR)
- {
- aff_buffer(BUFFER_ADD,"%s\n",errmsg_entry2partition(new_partition->errcode));
- res=1;
- }
- else
- {
- if((new_partition->lba<=partition_main_ext->lba) ||
- (new_partition->lba+new_partition->part_size-1 > partition_main_ext->lba+partition_main_ext->part_size-1))
- { /* Must be IN partition_main_ext */
- res=1;
- aff_buffer(BUFFER_ADD, msg_SAME_SPACE);
- aff_part_buffer(AFF_PART_ORDER,disk_car,partition_main_ext);
- aff_part_buffer(AFF_PART_ORDER,disk_car,new_partition);
- }
- }
- }
- if(res!=0)
- FREE(new_partition);
- else
- list_part=insert_new_partition(list_part,new_partition);
- }
- }
- partition_ext=partition_next_ext;
- } while ((res==0) && (partition_ext!=NULL) && (order<30));
- }
- return list_part;
- }
-
- static int test_MBR_over(t_param_disk *disk_car,t_list_part *list_part)
- {/* Tester le chevauchement des partitions */
- int res=0;
- t_list_part *element;
- for(element=list_part;element!=NULL;element=element->next)
- if((element->next!=NULL) && (element->part->lba + element->part->part_size - 1 >= element->next->part->lba))
- {
- res=1;
- aff_buffer(BUFFER_ADD, msg_SAME_SPACE);
- aff_part_buffer(AFF_PART_ORDER,disk_car,element->part);
- aff_part_buffer(AFF_PART_ORDER,disk_car,element->next->part);
- }
- return res;
- }
-